PagerDuty連携をクイック作成リンクから簡単にできるようにしてみた
現在運用保守チームでは、PagerDutyを活用してアラート発報にすぐに気づけるような仕組みを作っています。
今回はPagerDutyとアラート連携を行うためのLambda関数を作成してくれる、クイック作成リンクを作りました。クイック作成リンクを開くとCloudFormationのスタック作成ページに飛びます。パラメータを入力、展開するだけでLambda関数が作られて、アラートがPagerDutyに連携されます。
PagerDutyとは
最初に、PagerDutyが何か知らない人からすると、なぜアラートをPagerDutyに連携するのか分かりづらいと思うのでPagerDutyの主な機能を簡単に紹介します。
PagerDutyはインシデント管理ができるSaaSです。
アラートをPagerDutyに連携することで、インシデント作成が行われます。PagerDuty上から各インシデントごとに発生日時や担当者、現在のステータス(発報済み、確認済み, 解決済み)が見れます。インシデント発生時に担当者に通話してくれたり、担当者が反応しない場合は次の担当者に通話してくれたりします。また同じ特定のアラートに関してはアラートを飛ばさないようにするといった設定もできます。
PagerDutyのスマホアプリもあるので、スマホからエラー内容を確認できたり、ステータスの更新もできます。
PagerDuty連携について
自分たちが運用保守するプロジェクトで、よくあるアラート発報の構成は以下のようなものです。ここまでの構成は開発段階ですでに他の方が作ってくれています。
サーバーサイドでエラーが発生 → CloudWatch Logsにエラーログを吐く → メトリクスフィルターに引っかかる → AWS SNSでトピック作成 → Slack通知
今回このような構成に対して、PagerDuty連携のためLambda関数を追加します。
AWS SNSでトピック作成 → Lambda関数を起動して、PagerDutyのAPI呼び出し new → PagerDutyでインシデント作成
このLambda関数では、エラーの発生日時を元にCloudWatchからエラーログの取得をしてくれます。PagerDutyのAPI呼び出し時にログも連携してくれるので、PagerDuty上からエラーログが見れます。
またサーバーサイドのログ出力でLambda PowerToolsが使われている場合はトレースしたエラーログを取得するようしました。function_request_idを使ったログ検索をしています。この場合はエラーと関連する一連のログをPagerDuty上から確認できます。Lambda PowerToolsが使われていない場合はメトリクスフィルターに引っかかったログのみを取得しています。
あるユーザーがAPIを呼び出して、Lambdaが起動 受け取ったリクエスト内容をログ出力 DBからユーザー情報取得してログ出力 外部API呼び出しでリクエスト、レスポンス内容をログ出力 Lambdaが終了
この間に吐かれたログには同じfunction_request_idが付与され、一連のログとしてトレースできます。
Lambdaで動かしているスクリプトについては、以下のリンクから見れます。 https://github.com/shogo0421/pagerduty-lambda-cfn/blob/main/handler/src/index.ts
クイック作成リンク
クイック作成リンクとは、ブラウザで開くとCloudFormationのスタック作成ページに飛ぶことができるリンクです。予めS3に配置したcfnテンプレートを元にスタック作成ができます。
これまで上記の構成を追加するために、自分たちが保守する各プロジェクトごとにcdkのコードを追加する作業をしていました。
追加していたコードの内容は
- Lambda上で実行するスクリプトを追加
- PagerDuty連携のためのLambda作成
- LambdaにCloudWatchからログ取得する権限を追加
- SNSトピックにサブスクリプションを追加してLambdaを呼び出す
とかです。
これをテンプレート化してしまえば、プロジェクトごとにコードを追加する必要が無くて楽かもとか、PagerDutyを知らない人でもこの作業が簡単に出来そう、と思いクイック作成リンクを作りました。
以下のリンクを開いて、PagerDutyを導入したいAWS環境の権限を持ったロールに切り替えます。
エラー発報用のSNSトピックのARNと、PagerDutyのインテグレーションのキーとURLを入力して、作成ボタンを押せば導入できます。
またクイック作成リンクの末尾にクエリパラメータを追加すると、各パラメータが最初から入力された状態になります。([~]の角括弧も含め消して、各パラメータに置換。)
https://ap-northeast-1.console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/create/review?templateURL=https://quick-create-cfn-template.s3.ap-northeast-1.amazonaws.com/PagerdutyLambdaCdkStack.template.json&stackName=PagerdutyLambdaCdkStack ¶m_pagerDutyIntegrationKey=[~] ¶m_pagerDutyIntegrationUrl=[~] ¶m_errorTopicArn=[~]
エラー発報用トピックのARNはAWS環境から確認
PagerDutyのインテグレーションのキーとURLはPagerDutyから確認
動作確認
うまくアラートがPagerDuty連携できているか確認するため、CloudWatch Logs上に手動でイベントログを作成して、アラートを発生させます。
- CloudWatch Logsを開いて、エラー発報用のメトリクスフィルターが設定されたロググループを選択
- 適当なログストリームを開いて「ログイベントを作成」を選択
- 「test ERROR」などメトリクスフィルターに引っかかる文字を含むログを作成
(ERRORとErrorなど大文字と小文字でメトリクスフィルターの設定と違っていても反応しないので注意) - 数分(メトリクス生成の時間間隔分)待つとPagerDuty上でインシデント作成される
PagerDutyのスマホアプリを入れていると通知が来る
cfnテンプレートについて
クイック作成リンクを作るに当たって、S3に配置したcfnテンプレートは、CDKから生成しました。そのCDKプロジェクトのコードについては以下のリポジトリから確認できます。
https://github.com/shogo0421/pagerduty-lambda-cfn
S3に配置しているcfnテンプレートの内容は以下で見れます
面倒な点
デプロイできるリージョンについて
クイック作成リンクを使ってLambda関数をデプロイする場合、cfnテンプレートの他に、Lambda関数のスクリプト(ビルド生成物)もs3バケットに配置しないといけません。この時、Lambdaのデプロイ先のリージョンと、Lambdaのスクリプトが配置されたs3バケットのリージョンが、一致していないとデプロイに失敗します。そのため普段よく利用する2つのリージョン(東京、大阪)のS3には、スクリプトのビルド生成物を配置しています。しかし、それ以外のリージョンでは今回のクイック作成リンクは使えず、追加で作業が必要です。使うためには他のリージョンにもバケットの作成とビルド生成物の配置をします。今のところ頻繁に利用するリージョンが増えるわけではないので、そこまで支障をきたしませんが面倒です。
Lambda PowerToolsに依存
今回のPagerDuty連携用Lambdaが、CloudWatch Logsからエラーと関連した一連のログ取得をしてくれるのは、Lambda PowerToolsが導入されている場合のみです。それ以外の場合は、メトリクスフィルターに引っかかったログのみが取得されます。バックエンドがEC2の時など、Lambda PowerToolsを使わないことは結構多いです。毎回トレースしたエラーログまで表示できると不具合の調査がしやすく便利です。
補足
複数のAWS環境からログ取得してくるLambdaを共通基盤的に一つだけ作ることも考えましたが、一つのLambdaがクロスアカウントでログ取得することになります。Lambdaに必要最小限の権限のみを持たせることを考えると、同じ処理をするLambdaでも各環境ごとに作った方が良いと思いました。